/********************************************************************************************************************************
 * 《C ++ Primer》第五版中文版，读书笔记：按照书中的的示例源码和每一个小章节的课后习题，自己动手写代码实现，作为联系和测试。
 * Date: 2024-04-03 10:08
 * Author: dimon.chen 
 * EMali: 1181302388@qq.com 
 * 
 * 章节: 第三章 字符串，向量和数组
 *       3.5 C++内置类型数组
 *       3.5.2 访问数组元素
 * 
 ********************************************************************************************************************************/


#include <iostream>
#include <string>
#include <vector>
#include <cctype>           //C语言标准库头文件 ctpe.h 的 C++语言版本，定义了 toupper(), issapce(), isalpha() 的字符函数
#include <cstddef>           //C语言标准库头文件 stddef.h 的 C++ 语言版本，cstddef中定义了类型 size_t 
#include <iterator>         //C++11先标准定义的begin和end函数，可以获取到数组首元素的指针和尾元素下一位置的指针

using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::string;



// 与标准库类型 string 和 vector一样，数组也可以使用范围for和下标运算符来访问数组中的元素
// 在使用数组下标时通常将其定义为 size_t 类型
// size_t 类型定义在 cstddef 头文件中，cstddef 文件是C标准库头文件 stddef.h 的C++语言版本

int main(int argc, char *argv[])
{
    unsigned scores[11] = {};
    unsigned grade;

    while(cin >> grade){
        if(grade <= 100)
            ++scores[grade/10];
    }

    for(unsigned i : scores)
        cout << i << " ";
    cout << endl;

    size_t idx;


    // vector<int> ivec(1024*16);
    // for(auto i: ivec)
    //     cout << i << " ";
    // cout << endl;


    ///
	/// 3.5.2 节练习
	/// 练习3.30：指出下面代码中的索引错误
	///

	//错误：数组下标的范围从0开始到，数组的大小-1，而不是从1开始到size
	constexpr size_t array_size = 10;
	int ia[array_size];
	for(size_t idx = 1; idx <= array_size; idx++)
		ia[idx] = idx;



    ///
	/// 3.5.2 节练习
	/// 练习3.31：编写一个程序定义一个含有10个int型的数组，令数组的中元素的值就是下标值
	///
    int a1[10];
    for(size_t idx=0; idx < 10; idx++){
        a1[idx] = idx;
    }
    for(int i : a1)
        cout << i << " ";
    cout << endl;



    ///
	/// 3.5.2 节练习
	/// 练习3.32：将上一题中的数组拷贝给另外一个数组，利用vector重新实现程序，实现类似的功能
	///

    /// 内置数组类型，不支持用一个数组初始化另一个数组，也不支持把一个数组的赋值给另一个数组
    int a2[10]; 
    for(size_t idx=0; idx<10; idx++)
        a2[idx] = a1[idx];
    
    for(size_t idx=0; idx<10; idx++)
        cout << a1[idx] << " ";
    cout << endl;


    vector<int> v1;
    for(size_t idx=0; idx<10; idx++)
        v1.push_back(idx);
    

    for(auto i : v1)
        cout << i << " ";
    cout << endl;

    //vector<int> v2 = v1;
    vector<int> v2(v1);
    for(auto i : v2)
        cout << i << " ";
    cout << endl;


 

    ///////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////
    // 指针和数组
    // 通常情况下使用数组对象，编译器会自动把数组替换为执行数组首元素的指针
    // 数组也是迭代器
    // 数组可以递增从数组中的一个元素向前移动指向下一个元素
    // 类似迭代器，也可以通过获取指向数组尾元素下一位置的指针，尾后指针
    //
    //
    // 通常情况下对数组的操作实际上是对指针的操作，这一结论有很多隐含的意义。
    // 其中一层意义就是，使用数组作为 auto 变量的初始值时，编译器推断得到变量的类型是指针类型
    // 相反，使用 decltype() 关键字时，上述转换不会发生
    //
    //

    int arr[] = {0,1,2,3,4,5,6,7,8,9};
    int *pbeg = arr;
    int *pend = &arr[10];   //尾后指针，指向尾元素下一位置的指针
    while(pbeg != pend){
        cout << *pbeg << " ";
        pbeg++;
    }
    cout << endl;



    //c++11新标准定义的函数，传入数组作为函数的参数
    //begin返回指向数组首元素的指针
    //end返回指向数组尾元素下一位置的指针
    int *pb = std::begin(arr);
    int *pe = std::end(arr);
    for(; pb != pe; pb++){
        cout << *pb << " ";
    }
    cout << endl;



    vector<int> v3(std::begin(arr), std::end(arr));
    cout << "v3.size=" << v3.size();
    for(auto i : v3)
        cout << i << " ";
    cout << endl;

    return 0;
}